// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import * as ts from "typescript";
import * as fs from "fs";
import * as path from "path";
import * as morph from "ts-morph";

const expandOfAttributeTypeName = "ExpandOf";
const friendOfAttributeTypeName = "FriendOf";
const objectSystemAttributeTypeName = "ObjectSystemAttribute";
const awakeSystemTypeName = "AwakeSystem";
const awakeSystemTypeName1 = "Awake1System";
const awakeSystemTypeName2 = "Awake2System";
const awakeSystemTypeName3 = "Awake3System";
const awakeSystemTypeName4 = "Awake4System";
const loadSystemTypeName = "LoadSystem";
const updateSystemTypeName = "UpdateSystem";
const lateUpdateSystemTypeName = "LateUpdateSystem";
const destroySystemTypeName = "DestroySystem";

const rootFolderPath = "/Codes/scripts";
const expandOfAttributeFilePath = rootFolderPath + "/Decorator/Decorator";
const friendOfAttributeFilePath = rootFolderPath + "/Decorator/Decorator";
const objectSystemAttributeFilePath = rootFolderPath + "/Decorator/Decorator";
const awakeSystemFilePath = rootFolderPath + "/Core/Module/EventSystem/IAwakeSystem";
const loadSystemFilePath = rootFolderPath + "/Core/Module/EventSystem/ILoadSystem";
const updateSystemFilePath = rootFolderPath + "/Core/Module/EventSystem/IUpdateSystem";
const lateUpdateSystemFilePath = rootFolderPath + "/Core/Module/EventSystem/ILateUpdateSystem";
const destroySystemFilePath = rootFolderPath + "/Core/Module/EventSystem/IDestroySystem";

const declareModuleTemplate = `/**
 * 使用 Expand 扩展方法
 * 
 * 必须作出以下申明，才能调用对象的扩展方法
 */
declare module "{1}" {

    {0}
}
`;

const AwakeSystemTemplate = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}AwakeSystem extends AwakeSystem<{0}> {

    Awake(self: {0}): void {

    }

}`;

const AwakeSystemTemplate1 = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}Awake1System extends Awake1System<{0}, {1}> {

    Awake(self: {0}, a:{1}): void {

    }

}`;

const AwakeSystemTemplate2 = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}Awake2System extends Awake2System<{0}, {1}, {2}> {

    Awake(self: {0}, a:{1}, b:{2}): void {

    }

}`;

const AwakeSystemTemplate3 = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}Awake3System extends Awake3System<{0}, {1}, {2}, {3}> {

    Awake(self: {0}, a:{1}, b:{2}, c:{3}): void {

    }

}`;

const AwakeSystemTemplate4 = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}Awake4System extends Awake4System<{0}, {1}, {2}, {3}, {4}> {

    Awake(self: {0}, a:{1}, b:{2}, c:{3}, d:{4}): void {

    }

}`;

const LoadSystemTemplate = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}LoadSystem extends LoadSystem<{0}> {

    Load(self: {0}): void {

    }

}`;

const UpdateSystemTemplate = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}UpdateSystem extends UpdateSystem<{0}> {

    Update(self: {0}): void {
		
    }

}`;

const LateUpdateSystemTemplate = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}LateUpdateSystem extends LateUpdateSystem<{0}> {

    LateUpdate(self: {0}): void {
		
    }

}`;

const DestroySystemTemplate = `@FriendOf({0})
@ObjectSystemAttribute()
export class {0}DestroySystem extends DestroySystem<{0}> {

    Destroy(self: {0}): void {

    }

}`;

function convert(content: string, list: any[]) {
	if (typeof (list[0]) === 'object') {
		for (let key in list[0]) {
			let reg = new RegExp("({" + key + "})", "g");
			content = content.replace(reg, list[0][key]);
		}
	} else {
		for (let i = 0; i < list.length; i++) {
			let reg = new RegExp("({[" + i + "]})", "g");
			content = content.replace(reg, list[i]);
		}
	}
	return content;
}

function parse(...params: any[]) {
	let list = [];
	for (let i = 0; i < arguments.length; ++i) {
		list.push(arguments[i]);
	}
	let content = list.shift();
	content = convert(content, list);
	return content;
}

function visit(filePath: string, importClassType: string, node: ts.Node, iVisitSourceFile: ts.SourceFile, importedFilePathList: string[]) {
	if (!node) {
		return;
	}
	if (ts.isImportDeclaration(node)) {
		const namedBindings = node.importClause?.namedBindings;
		const importedFilePath = node.moduleSpecifier.getText(iVisitSourceFile).slice(1, -1);
		let isFouned = false;
		if (namedBindings) {
			if (ts.isNamedImports(namedBindings)) {
				for (const element of namedBindings.elements) {
					const elementType = element.propertyName ? element.propertyName.text : element.name.text;
					if (importClassType === elementType) {
						isFouned = true;
					}
				}
			} else if (ts.isNamespaceImport(namedBindings)) {
				const elementType = namedBindings.name.text;
				if (importClassType === elementType) {
					isFouned = true;
				}
			}
		}
		if (!isFouned) {
			return;
		}
		const iSourceFileFolder = path.dirname(filePath);
		const importedFileFullPath = path.join(iSourceFileFolder, importedFilePath);
		importedFilePathList.push(importedFileFullPath);
	}
	node.forEachChild(child => visit(filePath, importClassType, child, iVisitSourceFile, importedFilePathList));
}

function getSourceNode(filePath: string): morph.SourceFile | undefined {
	try {
		// 使用 typescript 编译器加载文件并解析为 AST 树.
		if (!fs.existsSync(filePath)) {
			console.log(`file not exist ${filePath}`);
		}
		const project = new morph.Project({ compilerOptions: { target: morph.ts.ScriptTarget.ES2016 } });
		project.addSourceFileAtPathIfExists(filePath);
		const morphSourceFile = project.getSourceFileOrThrow(filePath);
		return morphSourceFile;
	} catch (e) {

	}
	return undefined;
}

function findClassDeclaration(sourceFile: ts.SourceFile, filePath: string, classType: string): morph.ClassDeclaration | null {
	let classDecl: morph.ClassDeclaration | null = null;
	const filePathList: string[] = [];
	sourceFile.forEachChild(node => visit(filePath, classType, node, sourceFile, filePathList));
	if (filePathList.length !== 0) {
		const importedFileFullPath = filePathList[0];
		const importedSourceFile = getSourceNode(importedFileFullPath + ".ts");
		if (importedSourceFile) {
			const classDeclarations = importedSourceFile.getClasses();
			classDeclarations.forEach(classObj => {
				if (classObj.getName() === classType) {
					classDecl = classObj;
				}
			});
		}
	}
	return classDecl;
}

function getImportString(filePath: string, importFilePath: string) {
	let importString = "";
	const rootFolderPathIndex = filePath.indexOf(rootFolderPath);
	const nowFilePath = path.dirname(filePath.substring(rootFolderPathIndex).replace(rootFolderPath, ""));
	const nowImportFilePath = importFilePath.replace(rootFolderPath, "");
	const nowFilePathList = nowFilePath.substring(1).split("\/");
	const nowImportFilePathList = nowImportFilePath.substring(1).split("\/");
	const len = nowFilePathList.length;
	for (let i = 0; i < len; i++) {
		let tempFilePath = nowFilePathList[i];
		let tempImportFilePath = nowImportFilePathList[i];
		if (tempFilePath === tempImportFilePath) {
			continue;
		}
		importString += "../";
	}
	importString += nowImportFilePath.substring(1);
	return importString;
}

function addImportDeclaration(morphSourceFile: morph.SourceFile, importString: string, importTypeName: string) {
	const importDecl = morphSourceFile.getImportDeclaration(importString);
	if (!importDecl) {
		// 定义一组要导入到当前源代码文件中的命名成员列表。
		const namedImports: morph.ImportSpecifierStructure[] = [];
		const namedImportDecl: morph.ImportSpecifierStructure = {
			kind: morph.StructureKind.ImportSpecifier,
			name: importTypeName
		};
		namedImports.push(namedImportDecl);

		// 向当前源代码文件中添加一条指定模块路径、按名称列表方式选择性地导入 Bar 和 Foo 的导入声明语句。
		morphSourceFile.addImportDeclaration({
			moduleSpecifier: importString,
			namedImports
		});
	} else {
		let isImported = false;
		const namedImportSpecifiers = importDecl.getNamedImports();
		const len = namedImportSpecifiers.length;
		for (let i = 0; i < len; i++) {
			const namedImportSpecifier = namedImportSpecifiers[i];
			const namedImportName = namedImportSpecifier.getName();
			if (importTypeName === namedImportName) {
				isImported = true;
				break;
			}
		}
		if (!isImported) {
			const namedImportDecl: morph.ImportSpecifierStructure = {
				kind: morph.StructureKind.ImportSpecifier,
				name: importTypeName
			};
			// 向当前源代码文件中添加一条指定模块路径、按名称列表方式选择性地导入 Bar 和 Foo 的导入声明语句。
			importDecl.insertNamedImport(0, namedImportDecl);
		}
	}
}

async function declareCodeGenerate(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) {
	const editor = textEditor;
	if (!editor) {
		// 如果没有打开任何文件，则不做任何操作。
		return;
	}
	const document = editor.document;
	const uri = document.uri;
	if (!uri) {
		return;
	}
	// 文件路径
	const filePath = uri.path.substring(1);

	const selection = editor.selection;
	const position = selection.active;

	const fileContent = fs.readFileSync(filePath).toString();
	const sourceFile = ts.createSourceFile(
		filePath,
		fileContent,
		ts.ScriptTarget.Latest,
	);

	const project = new morph.Project({ compilerOptions: { target: morph.ts.ScriptTarget.ES2016 } });
	project.addSourceFileAtPathIfExists(filePath);

	// 将行号和列号转换为偏移量 offset
	const offset = ts.getPositionOfLineAndCharacter(sourceFile, position.line, position.character);

	// 获取包含当前光标位置的节点。
	const morphSourceFile = project.getSourceFileOrThrow(filePath);
	const nodeAtPosition = morphSourceFile?.getDescendantAtPos(offset);

	if (!nodeAtPosition) {
		return;
	}

	let classDecl: morph.ClassDeclaration | null = null;
	// 判断当前光标所在位置是否为 class 标识符，并获取该类定义。
	if (nodeAtPosition.getParent()?.getKind() === morph.ts.SyntaxKind.ClassDeclaration) {
		const classNode = nodeAtPosition.getParent();
		if (!classNode) {
			return;
		}
		if (classNode.getKind() !== morph.ts.SyntaxKind.ClassDeclaration) {
			return;
		}
		classDecl = classNode.asKindOrThrow(morph.ts.SyntaxKind.ClassDeclaration);
	}
	if (!classDecl) {
		return;
	}
	const decorators = classDecl.getDecorators();
	if (!decorators) {
		return;
	}
	const firstDecorator = decorators[0];
	if (!firstDecorator) {
		return;
	}
	const startLine = firstDecorator.getStartLineNumber(true) - 1;
	let classPosition: vscode.Position = new vscode.Position(startLine, 0);

	// 获取静态方法列表
	const decorator = classDecl.getDecorator(expandOfAttributeTypeName);
	if (!decorator) {
		return;
	}
	const args = decorator.getArguments();
	if (!args) {
		return;
	}
	const moduleNode = args[0];
	if (moduleNode.getKind() !== morph.ts.SyntaxKind.Identifier) {
		return;
	}
	const moduleDecl = moduleNode.asKindOrThrow(morph.ts.SyntaxKind.Identifier);
	if (!moduleDecl) {
		return;
	}
	const moduleType = moduleDecl.getFullText().trim();

	let moduleSpecifierValue = "";
	const importNodes = morphSourceFile.getImportDeclarations();
	importNodes.forEach(node => {
		const importDecl = node.asKindOrThrow(morph.ts.SyntaxKind.ImportDeclaration);
		const defaultImportNode = importDecl.getDefaultImport();
		if (defaultImportNode) {
			console.log(defaultImportNode.getKindName());
			return;
		}
		const namespaceImportNode = importDecl.getNamespaceImport();
		if (namespaceImportNode) {
			console.log(namespaceImportNode.getKindName());
			return;
		}
		const namedImportNodes = importDecl.getNamedImports();
		namedImportNodes.forEach(namedImportNode => {
			const namedImportDecl = namedImportNode.asKindOrThrow(morph.ts.SyntaxKind.ImportSpecifier);
			if (moduleType === namedImportDecl.getName()) {
				moduleSpecifierValue = importDecl.getModuleSpecifierValue();
			}
		});
	});
	if (moduleSpecifierValue === "") {
		moduleSpecifierValue = `./${moduleType}`;
	}

	let range: vscode.Range | null = null;
	morphSourceFile.forEachChild(node => {
		// 如果当前节点是 declare module 声明，则输出该声明模块名称及其他属性信息。
		if (node.getKind() !== morph.ts.SyntaxKind.ModuleDeclaration) {
			return;
		}
		const moduleDecl = node.asKindOrThrow(morph.ts.SyntaxKind.ModuleDeclaration);
		if (!moduleDecl) {
			return;
		}
		const interfaceDecl = moduleDecl.getInterface(moduleType);
		if (!interfaceDecl) {
			return;
		}
		const startLine = moduleDecl.getStartLineNumber(true) - 1;
		const startCharacter = 0;
		const endLine = moduleDecl.getEndLineNumber();
		const endCharacter = document.lineAt(endLine).text.length;

		range = new vscode.Range(
			startLine,
			startCharacter,
			endLine,
			endCharacter
		);
	});

	const interfaceMethods: morph.MethodSignatureStructure[] = [];
	const classStaticMethods = classDecl.getStaticMethods();
	if (classStaticMethods) {
		classStaticMethods?.forEach((node) => {
			if (!node.isStatic()) {
				return;
			}
			const parameters = node.getParameters();
			if (parameters.length === 0) {
				return;
			}
			const parameter = parameters.shift();
			if (!parameter) {
				return;
			}
			if (parameter.getName() !== "self") {
				return;
			}
			const parameterNode = parameter.getTypeNode();
			if (!parameterNode) {
				return;
			}
			const parameterDecl = parameterNode.asKindOrThrow(morph.ts.SyntaxKind.TypeReference);
			if (!parameterDecl) {
				return;
			}
			const parameterType = parameterDecl.getFullText().trim();
			if (parameterType !== moduleType) {
				return;
			}
			const methodName = node.getName();
			const methodParameters: morph.ParameterDeclarationStructure[] = [];
			parameters.forEach(pnode => {
				const pName = pnode.getName();
				const pTypeNode = pnode.getTypeNode()
				const pType = pTypeNode?.getFullText().trim();
				const methodParameter: morph.ParameterDeclarationStructure = {
					kind: morph.StructureKind.Parameter,
					name: pName,
					type: pType
				}
				methodParameters.push(methodParameter);
			});
			const returnTypeNode = node.getReturnTypeNode();
			const returnType = returnTypeNode?.getFullText().trim();
			const interfaceMethodNode: morph.MethodSignatureStructure = {
				kind: morph.StructureKind.MethodSignature,
				name: methodName,
				parameters: methodParameters,
				returnType: returnType
			}
			interfaceMethods.push(interfaceMethodNode);
		});
	}
	const interfaceSourceFile = project.createSourceFile("interface.ts", "", { overwrite: true });
	interfaceSourceFile.addInterface({
		name: moduleType,
		methods: interfaceMethods
	});
	let generatedCode = parse(declareModuleTemplate, interfaceSourceFile.getFullText(), moduleSpecifierValue);
	try {
		if (range) {
			editor.edit((editBuilder) => {
				if (range) {
					editBuilder.replace(range, generatedCode);
				}
			});
		} else {
			editor.edit((editBuilder) => {
				editBuilder.insert(classPosition, generatedCode + "\n");
			});
		}
		await vscode.commands.executeCommand('editor.action.formatDocument');
		await document.save();
		vscode.window.showInformationMessage("生成扩展方法申明成功.");
	} catch (e) {
		console.error(e);
		vscode.window.showErrorMessage("生成扩展方法申明失败.");
	}
}

async function sourceCodeGenerate(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) {
	const editor = textEditor;
	if (!editor) {
		// 如果没有打开任何文件，则不做任何操作。
		return;
	}
	const document = editor.document;
	const uri = document.uri;
	if (!uri) {
		return;
	}
	// 文件路径
	const filePath = uri.path.substring(1);

	const selection = editor.selection;
	const position = selection.active;

	const fileContent = fs.readFileSync(filePath).toString();
	// // 创建源文件对象
	const sourceFile = ts.createSourceFile(
		filePath,
		fileContent,
		ts.ScriptTarget.Latest,
	);

	const project = new morph.Project({ compilerOptions: { target: morph.ts.ScriptTarget.ES2016 } });
	project.addSourceFileAtPathIfExists(filePath);

	// 将行号和列号转换为偏移量 offset
	const offset = ts.getPositionOfLineAndCharacter(sourceFile, position.line, position.character);

	// 获取包含当前光标位置的节点。
	const morphSourceFile = project.getSourceFileOrThrow(filePath);
	const nodeAtPosition = morphSourceFile?.getDescendantAtPos(offset);

	if (!nodeAtPosition) {
		return;
	}

	let needRemoveStatement = false;
	let classType: string | undefined = "";
	let classDecl: morph.ClassDeclaration | null = null;
	// 判断当前光标所在位置是否为 class 标识符，并获取该类定义。
	if (nodeAtPosition.getParent()?.getKind() === morph.ts.SyntaxKind.ClassDeclaration) {
		const classNode = nodeAtPosition.getParent();
		if (!classNode) {
			return;
		}
		if (classNode.getKind() !== morph.ts.SyntaxKind.ClassDeclaration) {
			return;
		}
		classDecl = classNode.asKindOrThrow(morph.ts.SyntaxKind.ClassDeclaration);
		if (!classDecl) {
			return;
		}
		classType = classDecl.getName();
	} else if (nodeAtPosition.getParent()?.getKind() === morph.ts.SyntaxKind.ExpressionStatement) {
		const classNode = nodeAtPosition.getParent();
		if (!classNode) {
			return;
		}
		if (classNode.getKind() !== morph.ts.SyntaxKind.ExpressionStatement) {
			return;
		}
		const classIdentifer = classNode.asKindOrThrow(morph.ts.SyntaxKind.ExpressionStatement);
		classType = classIdentifer.getFullText().trim();
		classDecl = findClassDeclaration(sourceFile, filePath, classType);

		needRemoveStatement = true;
	}
	if (!classDecl) {
		return;
	}
	const classes = morphSourceFile.getClasses();
	const classNameList: string[] = [];
	classes.forEach(node => {
		const className = node.getName();
		if (!className) {
			return;
		}
		if (classNameList.indexOf(className) !== -1) {
			return;
		}
		classNameList.push(className);
	});
	// 获取继承列表和实现接口列表。
	let needGenerate = false;
	const classExtend = classDecl.getExtends();
	if (classExtend) {
		const classExtendType = classExtend.getFullText().trim();
		if (classExtendType === "Entity") {
			needGenerate = true;
		}
	}
	let needGenerateTypeList: string[] = [];
	let needGenerateTypeArgumentsListList: string[][] = [];
	const classImplements = classDecl.getImplements();
	if (classImplements) {
		classImplements?.forEach((node) => {
			const identifierNode = node.getExpression();
			const classImplementsType = identifierNode.getFullText().trim();
			const classImplementsTypeName = classType + classImplementsType.substring(1) + "System";
			if (classNameList.indexOf(classImplementsTypeName) !== -1) {
				return;
			}
			const typeArguments = node.getTypeArguments();
			const typeArgumentsList: string[] = [];
			typeArguments?.forEach(node => {
				const type = node.getFullText().trim();
				typeArgumentsList.push(type);
			});
			needGenerateTypeList.push(classImplementsType);
			needGenerateTypeArgumentsListList.push(typeArgumentsList);
		});
	}
	if (!needGenerate) {
		return;
	}

	const friendOfImportString = getImportString(filePath, friendOfAttributeFilePath);
	addImportDeclaration(morphSourceFile, friendOfImportString, friendOfAttributeTypeName);

	const objectSystemImportString = getImportString(filePath, objectSystemAttributeFilePath);
	addImportDeclaration(morphSourceFile, objectSystemImportString, objectSystemAttributeTypeName);

	let len = needGenerateTypeList.length;
	let generatedCode = "";
	for (let i = 0; i < len; i++) {
		let needGenerateType = needGenerateTypeList[i];
		let needGenerateTypeArgumentsList = needGenerateTypeArgumentsListList[i];
		switch (needGenerateType) {
			case "IAwake":
				{
					if (needGenerateTypeArgumentsList.length != 0) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(AwakeSystemTemplate, classType);
					const importString = getImportString(filePath, awakeSystemFilePath);
					addImportDeclaration(morphSourceFile, importString, awakeSystemTypeName);
				}
				break;
			case "IAwake1":
				{
					if (needGenerateTypeArgumentsList.length != 1) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(AwakeSystemTemplate1, classType, needGenerateTypeArgumentsList[0]);
					const importString = getImportString(filePath, awakeSystemFilePath);
					addImportDeclaration(morphSourceFile, importString, awakeSystemTypeName1);
				}
				break;
			case "IAwake2":
				{
					if (needGenerateTypeArgumentsList.length != 2) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(AwakeSystemTemplate2, classType, needGenerateTypeArgumentsList[0], needGenerateTypeArgumentsList[1]);
					const importString = getImportString(filePath, awakeSystemFilePath);
					addImportDeclaration(morphSourceFile, importString, awakeSystemTypeName2);
				}
				break;
			case "IAwake3":
				{
					if (needGenerateTypeArgumentsList.length != 3) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(AwakeSystemTemplate3, classType, needGenerateTypeArgumentsList[0], needGenerateTypeArgumentsList[1], needGenerateTypeArgumentsList[2]);
					const importString = getImportString(filePath, awakeSystemFilePath);
					addImportDeclaration(morphSourceFile, importString, awakeSystemTypeName3);
				}
				break;
			case "IAwake4":
				{
					if (needGenerateTypeArgumentsList.length != 4) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(AwakeSystemTemplate4, classType, needGenerateTypeArgumentsList[0], needGenerateTypeArgumentsList[1], needGenerateTypeArgumentsList[2], needGenerateTypeArgumentsList[3]);
					const importString = getImportString(filePath, awakeSystemFilePath);
					addImportDeclaration(morphSourceFile, importString, awakeSystemTypeName4);
				}
				break;
			case "ILoad":
				{
					if (needGenerateTypeArgumentsList.length != 0) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(LoadSystemTemplate, classType);
					const importString = getImportString(filePath, loadSystemFilePath);
					addImportDeclaration(morphSourceFile, importString, loadSystemTypeName);
				}
				break;
			case "IUpdate":
				{
					if (needGenerateTypeArgumentsList.length != 0) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(UpdateSystemTemplate, classType);
					const importString = getImportString(filePath, updateSystemFilePath);
					addImportDeclaration(morphSourceFile, importString, updateSystemTypeName);
				}
				break;
			case "ILateUpdate":
				{
					if (needGenerateTypeArgumentsList.length != 0) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(LateUpdateSystemTemplate, classType);
					const importString = getImportString(filePath, lateUpdateSystemFilePath);
					addImportDeclaration(morphSourceFile, importString, lateUpdateSystemTypeName);
				}
				break;
			case "IDestroy":
				{
					if (needGenerateTypeArgumentsList.length != 0) {
						throw new Error(`参数异常 ${needGenerateTypeArgumentsList}`);
					}
					generatedCode += parse(DestroySystemTemplate, classType);
					const importString = getImportString(filePath, destroySystemFilePath);
					addImportDeclaration(morphSourceFile, importString, destroySystemTypeName);
				}
				break;
		}
		if (i !== len - 1) {
			generatedCode += "\n\n";
		}
	}

	let needRemoveStatmentIndex = -1;
	if (needRemoveStatement) {
		const statements = morphSourceFile.getStatements();
		const statementsLen = statements.length;
		for (let i = 0; i < statementsLen; i++) {
			const statement = statements[i];
			const name = statement.getFullText().trim();
			if (classType === name) {
				needRemoveStatmentIndex = i;
			}
		}
	}
	if (needRemoveStatmentIndex !== -1) {
		morphSourceFile.removeStatement(needRemoveStatmentIndex);
	}

	const statements = morphSourceFile.getStatements();
	const index = statements.length;
	morphSourceFile.insertStatements(index, [
		"\n" + generatedCode
	]);

	try {
		let range: vscode.Range = new vscode.Range(
			0,
			0,
			document.lineCount - 1,
			document.lineAt(document.lineCount - 1).text.length
		);
		await editor.edit((editBuilder) => {
			editBuilder.replace(range, morphSourceFile.getFullText());
		});
		await vscode.commands.executeCommand('editor.action.formatDocument');
		await document.save();
		vscode.window.showInformationMessage("生成ObjectSystem类成功.");
	} catch (e) {
		console.error(e);
		vscode.window.showErrorMessage("生成ObjectSystem类失败.");
	}
}

export function activate(context: vscode.ExtensionContext) {
	console.log('Congratulations, your extension "ctetgencode" is now active!');

	let disposableDeclareCodeGenerate = vscode.commands.registerTextEditorCommand('extension.csg.declareCodeGenerate', declareCodeGenerate);
	let disposableSourceCodeGenerate = vscode.commands.registerTextEditorCommand('extension.csg.sourceCodeGenerate', sourceCodeGenerate);

	context.subscriptions.push(disposableDeclareCodeGenerate);
	context.subscriptions.push(disposableSourceCodeGenerate);
}

export function deactivate() { }
